package com.tiger.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tiger.utils.DateTimeUtils;
import com.tiger.utils.UpdateUtils;
import com.tiger.mapper.base.*;
import com.tiger.mapper.worksDisplay.AbleReportedUserIdMapper;
import com.tiger.mapper.worksDisplay.ErrorReplyInfoMapper;
import com.tiger.mapper.homePage.HotArticleMapper;
import com.tiger.mapper.worksDisplay.QuestionReplyInfoMapper;
import com.tiger.pojo.base.*;
import com.tiger.pojo.base.Collection;
import com.tiger.pojo.base.Error;
import com.tiger.pojo.homePage.HotArticle;
import com.tiger.pojo.worksDisplay.*;
import io.minio.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author HuXuehao (StudiousTiger)
 * @desc 这个类的作用是
 * @date 2022/2/12
 */
@Slf4j
@RestController
public class WorksDisplayController {
    @Autowired
    private HotArticleMapper hotArticleMapper;
    @Autowired
    private ErrorReplyInfoMapper errorReplyInfoMapper;
    @Autowired
    private QuestionReplyInfoMapper questionReplyInfoMapper;
    @Autowired
    private ErrorMapper errorMapper;
    @Autowired
    private QuestionMapper questionMapper;
    @Autowired
    private ReportMapper reportMapper;
    @Autowired
    private ErrorReplyMapper errorReplyMapper;
    @Autowired
    private QuestionReplyMapper questionReplyMapper;
    @Autowired
    private CollectionMapper collectionMapper;
    @Autowired
    private IgnoreReportMapper ignoreReportMapper;
    @Autowired
    private AbleReportedUserIdMapper ableReportedUserIdMapper;

    @Autowired
    private HttpServletRequest httpServletRequest;
    @Autowired
    private MinioClient minioClient;
    @Autowired
    private UpdateUtils updateUtil;

    @Value("${minio.bucketNameOfMdFile}")
    private String bucketNameOfMdFile;
    @Value("${minio.bucketNameOfMdPicture}")
    private String bucketNameOfMdPicture;




    /**
     * 获取作品展示页头部信息
     * @param workID
     * @return
     */
    @RequestMapping(value = "/worksDisplay/getHeadInfo/{workID}", name = "获取作品展示页头部信息/user")
    public String getHeadInfo(@PathVariable String workID){
        try {
            // hotArticleMapper 包含了所有error和question
            QueryWrapper<HotArticle> wrapper = new QueryWrapper<>();
            wrapper.eq("article_id",workID);
            List<HotArticle> res = hotArticleMapper.selectList(wrapper);
            if (res.size() != 0){
                for (HotArticle re : res) {
                    re.setUserHeadPhotoPath(updateUtil.getNewHeadPhotoURL(re.getUserHeadPhotoPath()));
                }
                return  JSON.toJSONString(res.get(0));
            } else{
                return "false";
            }
        } catch (Exception e) {
            log.error(e.toString());
            return "false";
        }
    }

    /**
     * 判断是否被举报
     * @param workID
     * @return
     */
    @RequestMapping(value = "/worksDisplay/title/weatherReport/{workID}", name = "判断是否被举报/user")
    public Boolean getWeatherReport(@PathVariable String workID){
        try {
            QueryWrapper<Report> wrapper = new QueryWrapper<>();
            wrapper.eq("reported_id",workID);
            wrapper.eq("user_id",httpServletRequest.getSession().getAttribute("userId"));
            List<Report> reports = reportMapper.selectList(wrapper);
            if (reports.size() == 0) {
                return false;
            } else {
                return true;
            }
        } catch (Exception e) {
            log.error(e.toString());
            return false;
        }
    }

    /**
     * 获取回复页码和回复总数
     * @param workID
     * @return
     */
    @RequestMapping(value = "/worksDisplay/getPagesAndTotal/{workID}", name = "获取回复页码和回复总数/user")
    public String getPagesAndTotal(@PathVariable String workID){
        PageAndTotal pageAndTotal = new PageAndTotal();
        try {
            QueryWrapper<HotArticle> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("article_id",workID);
            List<HotArticle> articles = hotArticleMapper.selectList(queryWrapper);
            String classify = articles.get(0).getClassify();

            if ("error".equals(classify)){
                Page<ErrorReplyInfo> page = new Page<>(1, 5);
                QueryWrapper<ErrorReplyInfo> wrapper = new QueryWrapper<>();
                wrapper.eq("error_id",workID);
                Page<ErrorReplyInfo> pages = errorReplyInfoMapper.selectPage(page, wrapper);

                pageAndTotal.setReplyTotal(pages.getTotal());
                pageAndTotal.setPageTotal(pages.getPages());
                return JSON.toJSONString(pageAndTotal);
            } else {
                Page<QuestionReplyInfo> page = new Page<>(1, 5);
                QueryWrapper<QuestionReplyInfo> wrapper = new QueryWrapper<>();
                wrapper.eq("question_id",workID);
                Page<QuestionReplyInfo> pages = questionReplyInfoMapper.selectPage(page, wrapper);

                pageAndTotal.setReplyTotal(pages.getTotal());
                pageAndTotal.setPageTotal(pages.getPages());
                return JSON.toJSONString(pageAndTotal);
            }
        } catch (Exception e) {
            log.error(e.toString());
            pageAndTotal.setReplyTotal(0L);
            pageAndTotal.setPageTotal(0L);
            return JSON.toJSONString(pageAndTotal);
        }
    }

    /**
     * 获取回复的信息
     * @param workID
     * @param currentPage
     * @return
     */
    @RequestMapping(value = "/worksDisplay/getReplyInfo/{workID}/{currentPage}", name = "获取回复的信息/user")
    public String getReplyInfo(@PathVariable String workID,@PathVariable int currentPage){
        try {
            // hotArticleMapper 包含了所有error和question,先根据workID查出文章的类型
            QueryWrapper<HotArticle> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("article_id",workID);
            List<HotArticle> articles = hotArticleMapper.selectList(queryWrapper);

            String classify = articles.get(0).getClassify();

            List<ReplyInfo> replyInfos = new ArrayList<>();
            // 根据类型查出回复的信息
            if ("error".equals(classify)){
                Page<ErrorReplyInfo> page = new Page<>(currentPage, 5);
                QueryWrapper<ErrorReplyInfo> wrapper = new QueryWrapper<>();
                wrapper.eq("error_id",workID);
                wrapper.orderByDesc("quality");
                Page<ErrorReplyInfo> pages = errorReplyInfoMapper.selectPage(page, wrapper);
                List<ErrorReplyInfo> errorReplyInfos = pages.getRecords();
                for (ErrorReplyInfo errorReplyInfo : errorReplyInfos) {
                    errorReplyInfo.setHeadPhotoPath(updateUtil.getNewHeadPhotoURL(errorReplyInfo.getHeadPhotoPath()));
                }
                if (errorReplyInfos.size() == 0){
                    return "empty";
                }
                for (ErrorReplyInfo info : errorReplyInfos) {
                    ReplyInfo replyInfo = new ReplyInfo();
                    replyInfo.setWorkReplyId(info.getErrorReplyId());
                    replyInfo.setWorkId(info.getErrorId());
                    replyInfo.setUserId(info.getUserId());
                    replyInfo.setUserNickname(info.getUserNickname());
                    replyInfo.setQuality(info.getQuality());
                    replyInfo.setHeadPhotoPath(info.getHeadPhotoPath());
                    replyInfo.setDate(info.getDate());
                    replyInfo.setContextAddr(info.getContextAddr());
                    replyInfo.setCollectedCount(info.getCollectedCount());
                    String markdownOfReply = getMarkdownOfReply(info.getContextAddr());
                    if (!"false".equals(markdownOfReply)){
                        String newTxtOfMarkdown = updateUtil.updateMDOfImgURL(markdownOfReply, bucketNameOfMdPicture);
                        replyInfo.setMarkdown(newTxtOfMarkdown);
                    } else {
                        replyInfo.setMarkdown("`哎呀，真是抱歉，暂时没有内容...`");
                    }
                    replyInfos.add(replyInfo);
                }
                return JSON.toJSONString(replyInfos);
            } else {
                Page<QuestionReplyInfo> page = new Page<>(currentPage, 5);
                QueryWrapper<QuestionReplyInfo> wrapper = new QueryWrapper<>();
                wrapper.eq("question_id",workID);
                wrapper.orderByDesc("quality");
                Page<QuestionReplyInfo> pages = questionReplyInfoMapper.selectPage(page, wrapper);
                List<QuestionReplyInfo> questionReplyInfos = pages.getRecords();
                for (QuestionReplyInfo questionReplyInfo : questionReplyInfos) {
                    questionReplyInfo.setHeadPhotoPath(updateUtil.getNewHeadPhotoURL(questionReplyInfo.getHeadPhotoPath()));
                }
                if (questionReplyInfos.size() == 0){
                    return "empty";
                }
                for (QuestionReplyInfo info : questionReplyInfos) {
                    ReplyInfo replyInfo = new ReplyInfo();
                    replyInfo.setWorkReplyId(info.getQuestionReplyId());
                    replyInfo.setWorkId(info.getQuestionId());
                    replyInfo.setUserId(info.getUserId());
                    replyInfo.setUserNickname(info.getUserNickname());
                    replyInfo.setQuality(info.getQuality());
                    replyInfo.setHeadPhotoPath(info.getHeadPhotoPath());
                    replyInfo.setDate(info.getDate());
                    replyInfo.setContextAddr(info.getContextAddr());
                    replyInfo.setCollectedCount(info.getCollectedCount());

                    String markdownOfReply = getMarkdownOfReply(info.getContextAddr());
                    if (!"false".equals(markdownOfReply)){
                        String newTxtOfMarkdown = updateUtil.updateMDOfImgURL(markdownOfReply, bucketNameOfMdPicture);
                        replyInfo.setMarkdown(newTxtOfMarkdown);
                    } else {
                       replyInfo.setMarkdown("`哎呀，真是抱歉，暂时没有内容...`");
                    }
                    replyInfos.add(replyInfo);
                }
                return JSON.toJSONString(replyInfos);
            }
        } catch (Exception e) {
            log.error(e.toString());
            return "false";
        }
    }

    /**
     * 根据MD文件的文件名获取MD中的文本
     * @param fileName
     * @return
     */
    @RequestMapping(value = "/worksDisplay/getMarkdown/{fileName}", name = "根据MD文件的文件名获取MD中的文本/user")
    public String getMarkdown(@PathVariable String fileName) {
        try {
            // 从 minio 中获取文件流
            InputStream inputStream = minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(bucketNameOfMdFile)
                            .object(fileName)
                            .build());

            // 将 InputStream 转换为 String
            String mdTxt = new BufferedReader(new InputStreamReader(inputStream))
                    .lines().collect(Collectors.joining(System.lineSeparator()));

            // 更新MD中的图片链接表达式
            return updateUtil.updateMDOfImgURL(mdTxt, bucketNameOfMdPicture);

        } catch (Exception e) {
           log.error(e.toString());
           return "false";
        }

    }

    /**
     * 作品标题的收藏（顶上去）
     * @param workId
     * @param classify
     * @param star
     * @return
     */
    @RequestMapping(value = "/worksDisplay/title/collection/{workId}/{classify}/{star}", name = "作品标题的点赞/user")
    public String titleCollection(@PathVariable String workId, @PathVariable String classify, @PathVariable int star){
        if ("error".equals(classify)) {
            UpdateWrapper<Error> wrapper = new UpdateWrapper<>();
            wrapper.eq("error_id",workId);
            wrapper.set("error_star",star);
            int res = errorMapper.update(null, wrapper);
            if (res == 1) {
                return "true";
            } else {
                return "false";
            }
        } else {
            UpdateWrapper<Question> wrapper = new UpdateWrapper<>();
            wrapper.eq("question_id",workId);
            wrapper.set("question_star",star);
            int res = questionMapper.update(null, wrapper);
            if (res == 1) {
                return "true";
            } else {
                return "false";
            }
        }

    }

    /**
     * 举报标题和举报回复
     * @param reportedId
     * @param reportedClassify
     * @return
     */
    @RequestMapping(value = "/worksDisplay/report/{reportedId}/{reportedClassify}", name = "举报标题和举报回复/user")
    public String report(@PathVariable String reportedId,@PathVariable String reportedClassify){
        String userId = (String) httpServletRequest.getSession().getAttribute("userId");

        Report report = new Report();
        report.setUserId(userId);
        report.setReportedId(reportedId);
        report.setReportedClassify(reportedClassify);
        report.setDate(DateTimeUtils.currentDateTime2SQLTimestamp());
        int res = reportMapper.insert(report);
        if (res == 1){
            // 需要在举报成功后，将被举报用户从ignore_report中删除
            QueryWrapper<AbleReportedUserId> wrapper = new QueryWrapper<>();
            wrapper.eq("target_id",reportedId);
            List<AbleReportedUserId> ableReportedUserIds = ableReportedUserIdMapper.selectList(wrapper);
            if (ableReportedUserIds.size() > 0) {
                String willDeleteId = ableReportedUserIds.get(0).getUserId();
                //结合Map实现删除的条件
                Map<String,Object> conditionsMap=new HashMap<>();
                conditionsMap.put("reported_id", willDeleteId);
                ignoreReportMapper.deleteByMap(conditionsMap);
            }
            return "true";
        } else {
            return "false";
        }
    }

    /**
     * 发布评论
     * @return
     */
    @RequestMapping(value = "/worksDisplay/publishReply", name = "发布评论/user", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    public String publishReply(@RequestBody JSONObject jsonParam){
        try {
            ReplyPojo replyPojo = JSON.parseObject(String.valueOf(jsonParam), ReplyPojo.class);

            QueryWrapper<HotArticle> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("article_id",replyPojo.getRepliedId());
            List<HotArticle> articles = hotArticleMapper.selectList(queryWrapper);
            String classify = articles.get(0).getClassify();
            String userId = (String) httpServletRequest.getSession().getAttribute("userId");
            if ("error".equals(classify)) {
                ErrorReply errorReply = new ErrorReply();
                errorReply.setUserId(userId);
                errorReply.setErrorId(replyPojo.getRepliedId());
                errorReply.setDate(DateTimeUtils.currentDateTime2SQLTimestamp());
                String fileName = uploadMD(replyPojo.getText(), null);
                errorReply.setContextAddr(fileName);
                int res = errorReplyMapper.insert(errorReply);
                if (res == 1) {
                    return "true";
                } else {
                    return "false";
                }
            } else {
                QuestionReply questionReply = new QuestionReply();
                questionReply.setUserId(userId);
                questionReply.setQuestionId(replyPojo.getRepliedId());
                questionReply.setDate(DateTimeUtils.currentDateTime2SQLTimestamp());
                String fileName = uploadMD(replyPojo.getText(), null);
                questionReply.setContextAddr(fileName);
                int res = questionReplyMapper.insert(questionReply);
                if (res == 1) {
                    return "true";
                } else {
                    return "false";
                }
            }
        } catch (Exception e) {
            log.error(e.toString());
            return "false";
        }
    }

    /**
     * 点击回复的“编辑”按钮是时根据 filename 获取对应文件中的文本
     * @param fileName
     * @return
     */
    private String getMarkdownOfReply(String fileName) {
        try {
            // 从 minio 中获取文件流
            InputStream inputStream = minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(bucketNameOfMdFile)
                            .object(fileName)
                            .build());

            // 将 InputStream 转换为 String
            String res = new BufferedReader(new InputStreamReader(inputStream))
                    .lines().collect(Collectors.joining(System.lineSeparator()));
            String newTxtOfMarkdown = updateUtil.updateMDOfImgURL(res, bucketNameOfMdPicture);
            return newTxtOfMarkdown;

        } catch (Exception e) {
            log.error(e.toString());
            return "false";
        }
    }

    /**
     * 更新评论
     * @return
     */
    @RequestMapping(value = "/worksDisplay/updateReply", name = "更新评论/user", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
    public String updateMarkdownOfReply(@RequestBody JSONObject jsonParam){
        try {
            ReplyPojo replyPojo = JSON.parseObject(String.valueOf(jsonParam), ReplyPojo.class);
            QueryWrapper<HotArticle> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("article_id",replyPojo.getRepliedId());
            List<HotArticle> articles = hotArticleMapper.selectList(queryWrapper);
            String classify = articles.get(0).getClassify();
            if ("error".equals(classify)) {
                ErrorReply errorReply = errorReplyMapper.selectById(replyPojo.getReplyId());
                uploadMD(replyPojo.getText(), errorReply.getContextAddr());
                return "true";
            } else {
                QuestionReply questionReply = questionReplyMapper.selectById(replyPojo.getReplyId());
                uploadMD(replyPojo.getText(),questionReply.getContextAddr());
                return "true";
            }
        } catch (Exception e) {
            log.error(e.toString());
            return "false";
        }
    }


    /**
     * 上传MD文件，并返回文件名
     * @param str 用于生成MD文件
     * @param fileName 自定义文件名，主要用于更新文章时覆盖原本的文章
     * @return 返回的是上传到minio的文件的文件名
     */
    private String uploadMD(String str,String fileName){
        if (fileName == null){
            fileName = (UUID.randomUUID() + "").replaceAll("-","") + ".txt";
        }

        try {
            // 将String转换为InputStream
            InputStream in = new ByteArrayInputStream(str.getBytes(StandardCharsets.UTF_8));

            // 判断目标 bucket 是否存在
            boolean exit = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketNameOfMdFile).build());
            if (!exit){
                // 创建名为 bucketName 的 bucket
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketNameOfMdFile).build());
            }
            // 上传文件
            minioClient.putObject(
                    PutObjectArgs.builder()
                            .bucket(bucketNameOfMdFile)
                            .object(fileName)
                            .stream(in,in.available(),-1)
                            .build()
            );
            return fileName;
        } catch (Exception e) {
            log.error(e.toString());
            return "false";
        }
    }


    /**
     * 删除指定的回复
     * @param replyId
     * @param workId
     * @return
     */
    @RequestMapping(value = "/worksDisplay/delete/{replyId}/{workId}", name = "删除指定的回复/user")
    public String delete(@PathVariable String replyId, @PathVariable String workId){
        try {
            QueryWrapper<HotArticle> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("article_id",workId);
            List<HotArticle> articles = hotArticleMapper.selectList(queryWrapper);
            String classify = articles.get(0).getClassify();
            if ("error".equals(classify)) {
                int res = errorReplyMapper.deleteById(replyId);
                if (res == 1) {
                    return "true";
                } else {
                    return "false";
                }
            } else {
                int res = questionReplyMapper.deleteById(replyId);
                if (res == 1) {
                    return "true";
                } else {
                    return "false";
                }
            }
        } catch (Exception e) {
            log.error(e.toString());
            return "false";
        }

    }

    /**
     * 点赞指定的回复
     * @param replyId
     * @param workId
     * @return
     */
    @RequestMapping(value = "/worksDisplay/quality/{replyId}/{workId}/{quality}", name = "点赞指定的回复/user")
    public String quality(@PathVariable String replyId, @PathVariable String workId, @PathVariable int quality){
        try {
            QueryWrapper<HotArticle> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("article_id",workId);
            List<HotArticle> articles = hotArticleMapper.selectList(queryWrapper);
            String classify = articles.get(0).getClassify();

            if ("error".equals(classify)) {
                UpdateWrapper<ErrorReply> wrapper = new UpdateWrapper<>();
                wrapper.eq("error_reply_id",replyId);
                wrapper.set("quality",quality);
                int res = errorReplyMapper.update(null, wrapper);
                if (res == 1) {
                    return "true";
                } else {
                    return "false";
                }
            } else {
                UpdateWrapper<QuestionReply> wrapper = new UpdateWrapper<>();
                wrapper.eq("question_reply_id",replyId);
                wrapper.set("quality",quality);
                int res = questionReplyMapper.update(null, wrapper);
                if (res == 1) {
                    return "true";
                } else {
                    return "false";
                }
            }
        } catch (Exception e) {
            log.error(e.toString());
            return "false";
        }
    }


    /**
     * 收藏指定的回复
     * @param replyId
     * @return
     */
    @RequestMapping(value = "/worksDisplay/collection/{replyId}/{workId}", name = "收藏指定的回复/user")
    public String collection(@PathVariable String replyId, @PathVariable String workId) {
        try {
            String userId = (String) httpServletRequest.getSession().getAttribute("userId");
            Collection collection = new Collection();
            collection.setUserId(userId);
            collection.setCollectedId(replyId);
            collection.setDate(DateTimeUtils.currentDateTime2SQLTimestamp());

            QueryWrapper<HotArticle> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq("article_id",workId);
            List<HotArticle> articles = hotArticleMapper.selectList(queryWrapper);
            String classify = articles.get(0).getClassify();
            if ("error".equals(classify)) {
                collection.setContextClassify(0);
            } else {
                collection.setContextClassify(1);
            }

            int res = collectionMapper.insert(collection);
            if (res == 1) {
                return "true";
            } else {
                return "false";
            }
        } catch (Exception e) {
            log.error(e.toString());
            return "false";
        }
    }

    /**
     * 取消指定的收藏
     * @param replyId
     * @return
     */
    @RequestMapping(value = "/worksDisplay/cancelCollection/{replyId}", name = "取消指定的收藏/user")
    public String cancelCollection(@PathVariable String replyId) {
        try {
            QueryWrapper<Collection> wrapper = new QueryWrapper<>();
            wrapper.eq("user_id",httpServletRequest.getSession().getAttribute("userId"));
            wrapper.eq("collected_id",replyId);
            List<Collection> collections = collectionMapper.selectList(wrapper);
            int res = collectionMapper.deleteById(collections.get(0).getCollectionId());
            if (res == 1) {
                return "true";
            } else {
                return "false";
            }
        } catch (Exception e) {
            log.error(e.toString());
            return "false";
        }
    }

    /**
     * 获取当前用户收藏的所有的ID
     * @return
     */
    @RequestMapping(value = "/worksDisplay/getUserCollectedId", name = "获取当前用户收藏的所有的ID/user")
    public String getUserCollectedId() {
        try {
            QueryWrapper<Collection> wrapper = new QueryWrapper<>();
            wrapper.eq("user_id",httpServletRequest.getSession().getAttribute("userId"));
            List<Collection> res = collectionMapper.selectList(wrapper);
            String[] collectedId = new String[res.size()+1];
            if (res.size() > 0) {
                for (int i=0; i<res.size(); i++) {
                    collectedId[i] = res.get(i).getCollectedId();
                }
            }
            return JSON.toJSONString(collectedId);
        } catch (Exception e) {
            log.error(e.toString());
            return JSON.toJSONString( new String[] {null} );
        }
    }

    @RequestMapping(value = "/worksDisplay/userReportReplyList", name = "获取文章回复信息/user")
    public String getUerReportReplyList(){
        try {
            QueryWrapper<Report> wrapper = new QueryWrapper<>();
            wrapper.eq("user_id",httpServletRequest.getSession().getAttribute("userId"));
            List<Report> res = reportMapper.selectList(wrapper);
            String[] reportedId = new String[res.size()+1];
            if (res.size() > 0) {
                for (int i=0; i<res.size(); i++) {
                    reportedId[i] = res.get(i).getReportedId();
                }
            }
            return JSON.toJSONString(reportedId);
        } catch (Exception e) {
            log.error(e.toString());
            return JSON.toJSONString( new String[] {null} );
        }
    }
}
